package org.jeecg.module.flow.meter.tcpserver.tcpServer;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.module.flow.meter.tcpserver.constant.FlowMeterNettyConstant;
import org.jeecg.module.flow.meter.tcpserver.tcpServer.handler.Cat1MessageDecoderHandler;
import org.jeecg.module.flow.meter.tcpserver.tcpServer.handler.TcpConnectionHandler;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * @Author: 86176
 * @Date: 2024-05-21 9:41
 * @Version: 1.0
 */
@Service
@Slf4j
public class TcpServer extends Thread {
    @Override
    public void run() {
        try {
            bind(FlowMeterNettyConstant.PORT);
        } catch (Exception e) {
            log.error("服务器启动失败:{}", e.getMessage());
        }
    }

    public void bind(int port) {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup(FlowMeterNettyConstant.WORKER_THREADS);

        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, FlowMeterNettyConstant.BACKLOG_SIZE)
                    .childHandler(new ChildChannelHandler());

            ChannelFuture f = b.bind(port).sync();
            log.info("流量计TCP服务器已启动!");

            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            log.error("服务器启动时发生中断异常", e);
        } catch (Exception e) {
            log.error("服务器启动失败", e);
            handleStartFailure();
        } finally {
            shutdownGracefully(bossGroup, workerGroup);
        }
    }

    private void handleStartFailure() {
        int retryCount = 0;
        while (true) {
            log.warn("服务启动失败，准备第{}次重试...", retryCount + 1);
            try {
                TimeUnit.SECONDS.sleep((long) Math.pow(2, retryCount)); // 指数退避
                bind(FlowMeterNettyConstant.PORT);
                return; // 成功则直接返回
            } catch (InterruptedException e) {
                log.error("重试期间发生中断异常", e);
                Thread.currentThread().interrupt();
                return;
            } catch (Exception e) {
                retryCount++;
                if (retryCount >= FlowMeterNettyConstant.MAX_RETRY_ATTEMPTS) {
                    log.error("达到最大重试次数，不再尝试");
                    break;
                }
            }
        }
        // 处理最终失败的情况，如发送告警等
    }

    private void shutdownGracefully(EventLoopGroup... groups) {
        for (EventLoopGroup group : groups) {
            group.shutdownGracefully();
        }
    }

    private static class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
        @Override
        protected void initChannel(SocketChannel ch) throws Exception {
            //自定义消息解析
            ch.pipeline().addLast(new Cat1MessageDecoderHandler());
            //自定义消息处理
            ch.pipeline().addLast(new TcpConnectionHandler());
            //自定义连接超时类
            //ch.pipeline().addLast(new IdleStateHandler(30, 0, 0));
        }
    }

}
